function Observer(data) {
	this.data = data;
	this.walk(data);
}

Observer.prototype = {
	constructor: Observer,
	walk: function (data) {
		var me = this;
		// 遍历data所有属性，通过defineReactive，将属性定义成响应式属性
		Object.keys(data).forEach(function (key) {
			me.convert(key, data[key]);
		});
	},
	convert: function (key, val) {
		this.defineReactive(this.data, key, val);
	},

	defineReactive: function (data, key, val) {
		// 每个响应式属性都有一个dep对象
		var dep = new Dep();
		// 递归调用，让属性值中的属性也要变成响应式
		// 为了确保data中所有属性都要变成响应式
		var childObj = observe(val);

		// 定义响应式
		// 通过Object.defineProperty对data中的属性进行重新定义，定义get/set
		// 当你读取原data数据属性时，会建立起响应式联系并返回属性值
		// 当你设置原data数据属性时，更新属性值并触发用户界面的更新（从而达到响应式）
		Object.defineProperty(data, key, {
			enumerable: true, // 可枚举
			configurable: false, // 不能再define
			get: function () {
				if (Dep.target) {
					// 建立响应式联系
					dep.depend();
				}
				// 返回属性值
				return val;
			},
			set: function (newVal) {
				if (newVal === val) {
					return;
				}
				// 更新属性值
				val = newVal;
				// 新的值是object的话，将新值定义成响应式
				childObj = observe(newVal);
				// 触发用户界面的更新
				dep.notify();
			},
		});
	},
};

function observe(value, vm) {
	// 判断value是否是对象
	if (!value || typeof value !== "object") {
		return;
	}

	return new Observer(value);
}

var uid = 0;

function Dep() {
	this.id = uid++;
	this.subs = [];
}

Dep.prototype = {
	addSub: function (sub) {
		this.subs.push(sub);
	},

	depend: function () {
		// watcher.addDep(dep)
		Dep.target.addDep(this);
	},

	removeSub: function (sub) {
		var index = this.subs.indexOf(sub);
		if (index != -1) {
			this.subs.splice(index, 1);
		}
	},

	notify: function () {
		this.subs.forEach(function (sub) {
			sub.update();
		});
	},
};

Dep.target = null;
